package services

import (
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"github.com/pkg/errors"
	"strconv"
	"weiboxs.com/new_h_glasses/models"
	"weiboxs.com/new_h_glasses/utils"
)

func (q *QueryParamsStatistics) StatisticsGetDepartment() map[int64]map[string]interface{} {
	maps := make(map[int64]map[string]interface{})
	deps := models.DepartmentDataList()
	for _, v := range deps {
		maps[v.Id] = map[string]interface{}{"Name": v.Name, "Id": v.Id}
	}
	return maps
}

type QueryParamsStatistics struct {
	StartDate    string
	EndDate      string
	DepartmentId int64 //门店ID
	Filter       string
	TypeId       int //类型ID
}

//销售汇总
type RetailStatistics struct {
	RealName       string
	Mobile         string
	TypeName       string  //类型
	DepName        string  //门店
	Identifier     string  //单号
	BusinessName   string  //营业员
	TotalMoney     float64 //总金额
	ChangesMmoney  float64 //调减金额
	PaymentType    string  //1已付2未付
	PaymentTypeWf  float64 //未付金额
	PaymentTypeSK  float64 //刷卡金额
	PaymentTypeWX  float64 //微信金额
	PaymentTypeZFB float64 //支付宝金额
	PaymentTypeXJ  float64 //现金
	CreatedAt      string  //创建时间
	CreatedBy      string  //创建人
}

func (q *QueryParamsStatistics) queryRetail() []*models.Retails {
	query := orm.NewOrm().QueryTable(models.RetailsTableName()).RelatedSel("Archives")

	cond := orm.NewCondition()
	cond = cond.AndCond(cond.And("created_at__gte", utils.GetTimeParse(q.StartDate)).And("created_at__lte", utils.GetTimeParse(q.EndDate)))

	if q.DepartmentId > 0 {
		cond = cond.And("department_id", q.DepartmentId)
	}
	if len(q.Filter) > 0 {
		cond = cond.And("manual_number", q.Filter)
	}

	query = query.SetCond(cond)
	retails := make([]*models.Retails, 0)
	query = query.OrderBy("created_at")
	if _, err := query.All(&retails); err != nil {
		return nil
	}

	return retails
}

func (q *QueryParamsStatistics) Retail() ([]*RetailStatistics, error) {

	retails := q.queryRetail()

	deps := q.StatisticsGetDepartment()

	statistics := make([]*RetailStatistics, 0)

	var totalMoney, changesMmoney, paymentTypeWf, paymentTypeSK, paymentTypeWX, paymentTypeZFB, paymentTypeXJ float64

	for _, v := range retails {
		st := &RetailStatistics{}
		if v.IsPayment != 5 {
			continue
		}
		st.RealName = v.Archives.Realname
		st.Mobile = v.Archives.Mobile
		st.BusinessName = v.BusinessName

		if n, ok := deps[v.DepartmentId]; ok {
			st.DepName = n["Name"].(string)
		}
		st.Identifier = v.ManualNumber

		st.PaymentTypeZFB = v.AlipayMoney
		st.PaymentTypeWX = v.WechatMoney
		st.PaymentTypeSK = v.CardMoney
		st.PaymentTypeXJ = v.CashMoney

		paymentTypeSK += st.PaymentTypeSK   //刷卡
		paymentTypeZFB += st.PaymentTypeZFB //刷卡
		paymentTypeWX += st.PaymentTypeWX   //刷卡
		paymentTypeXJ += st.PaymentTypeXJ   //刷卡

		st.TotalMoney = v.TotalMoney
		totalMoney += st.TotalMoney //累计总金额

		st.ChangesMmoney = v.ChangesMoney
		changesMmoney += st.ChangesMmoney //累计调减金额

		switch v.IsPayment {
		case 1: //已付
			st.PaymentType = "已付"
		case 2: //未付
			st.PaymentType = "未付"
			paymentTypeSK += st.PaymentTypeSK
		}

		st.CreatedAt = utils.GetDate(v.CreatedAt)
		st.CreatedBy = v.CreatedBy

		statistics = append(statistics, st)
	}

	//最终汇总数据
	total := &RetailStatistics{}
	total.Identifier = "汇总"
	total.TotalMoney, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", totalMoney), 64)
	total.PaymentTypeXJ, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", paymentTypeXJ), 64)
	total.PaymentTypeZFB, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", paymentTypeZFB), 64)
	total.PaymentTypeWX, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", paymentTypeWX), 64)
	total.PaymentTypeWf, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", paymentTypeWf), 64)
	total.PaymentTypeSK, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", paymentTypeSK), 64)
	total.ChangesMmoney, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", changesMmoney), 64)
	statistics = append(statistics, total)

	return statistics, nil
}

//销售产品明细
type RetailDetailedStatistics struct {
	Identifier    string //单据号
	DepName       string //门店
	Amount        int64  //产品数量
	ProductName   string
	Diopter       string
	Astigmatism   string
	ColourNumber  string
	ModelNumber   string
	OriginalPrice float64 //产品原价
	DiscountRate  float64 //产品折扣率
	UnitPrice     float64 //产品折后单价
	TotalPrice    float64 //折后单价*产品数量
	CreatedAt     string  //创建时间
	CreatedBy     string  //创建人

	TradePrice  float64 //进货价
	ProfitPrice float64 //利润
	ClassName   string  //类型
}

func (q *QueryParamsStatistics) RetailDetailed() ([]*RetailDetailedStatistics, error) {
	query := orm.NewOrm().QueryTable(models.RetailsDataTableName()).RelatedSel("Retails", "Products", "Snd")

	cond := orm.NewCondition()
	cond = cond.AndCond(cond.And("retails__created_at__gte", utils.GetTimeParse(q.StartDate)).And("retails__created_at__lte", utils.GetTimeParse(q.EndDate)))

	if q.DepartmentId > 0 {
		cond = cond.And("retails__department_id", q.DepartmentId)
	}
	if len(q.Filter) > 0 {
		cond = cond.And("retails__manual_number", q.Filter)
	}
	query = query.SetCond(cond)
	retailsData := make([]*models.RetailsData, 0)

	if _, err := query.All(&retailsData); err != nil {
		return nil, err
	}
	statistics := make([]*RetailDetailedStatistics, 0)

	deps := q.StatisticsGetDepartment()

	var (
		TotalOriginalPrice float64 //总原价
		TotalUnitPrice     float64 //总单价
		TotalTotalPrice    float64 //总金额
		TotalTradePrice    float64 //总进价
		TotalProfitPrice   float64 //总利润
	)

	for _, v := range retailsData {
		st := &RetailDetailedStatistics{}
		if v.Retails.IsPayment != 5 {
			continue;
		}
		st.Identifier = v.Retails.ManualNumber //单号
		if n, ok := deps[v.Retails.DepartmentId]; ok {
			st.DepName = n["Name"].(string)
		}

		st.CreatedBy = v.Retails.CreatedBy
		st.CreatedAt = utils.GetDate(v.Retails.CreatedAt)
		st.OriginalPrice = v.OriginalPrice
		st.DiscountRate = v.DiscountRate
		st.UnitPrice = v.UnitPrice
		st.TotalPrice = v.TotalPrice
		st.ProductName = fmt.Sprintf("%s-%s", v.Products.BrandName, v.Products.FullName)
		st.ModelNumber = v.Snd.Model
		st.ColourNumber = v.Snd.Color
		st.Diopter = v.Snd.Sph
		st.Astigmatism = v.Snd.Cyl

		st.ProfitPrice = st.TotalPrice - (st.TradePrice * float64(st.Amount)) //总金额减去进货金额
		st.ProfitPrice, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", st.ProfitPrice), 64)
		st.ClassName = ""

		TotalOriginalPrice += st.OriginalPrice
		TotalUnitPrice += st.UnitPrice
		TotalTotalPrice += st.TotalPrice
		TotalTradePrice += st.TradePrice
		TotalProfitPrice += st.ProfitPrice

		statistics = append(statistics, st)
	}

	totalSt := &RetailDetailedStatistics{}
	totalSt.DepName = "合计"
	totalSt.OriginalPrice, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", TotalOriginalPrice), 64)
	totalSt.UnitPrice, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", TotalUnitPrice), 64)
	totalSt.TotalPrice, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", TotalTotalPrice), 64)
	totalSt.TradePrice, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", TotalTradePrice), 64)
	totalSt.ProfitPrice, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", TotalProfitPrice), 64)

	statistics = append(statistics, totalSt)

	return statistics, nil
}

//出入库汇总
type EntryStatistics struct {
	Identifier    string //单据号
	DepName       string //门店
	ProductNumber int64
	Postage       float64
	TypeName      string
	TotalMoney    float64
	CreatedAt     string //创建时间
	CreatedBy     string //创建人
}

var types map[int]string = map[int]string{10: "入库", 20: "退库", 30: "报损"}

func (q *QueryParamsStatistics) Entry() ([]*EntryStatistics, error) {
	query := orm.NewOrm().QueryTable(models.ErpEntryTableName())

	cond := orm.NewCondition()
	cond = cond.And("auditing", 4)
	cond = cond.AndCond(cond.And("created_at__gte", utils.GetTimeParse(q.StartDate)).And("created_at__lte", utils.GetTimeParse(q.EndDate)))

	if q.DepartmentId > 0 {
		cond = cond.And("department_id", q.DepartmentId)
	}
	if q.TypeId > 0 {
		cond = cond.And("typeid", q.TypeId)
	}
	if len(q.Filter) > 0 {
		cond = cond.And("number", q.Filter)
	}
	query = query.SetCond(cond)
	erpEntry := make([]*models.ErpEntry, 0)

	if _, err := query.All(&erpEntry); err != nil {
		return nil, err
	}
	statistics := make([]*EntryStatistics, 0)

	deps := q.StatisticsGetDepartment()

	var (
		totalMoney     float64
		totalProNumber int64
	)

	for _, v := range erpEntry {
		st := &EntryStatistics{}
		st.Identifier = v.Number
		if n, ok := deps[v.DepartmentId]; ok {
			st.DepName = n["Name"].(string)
		}

		st.TotalMoney = v.Money
		st.ProductNumber = v.ProNumber
		st.CreatedAt = utils.GetDate(v.CreatedAt)
		st.CreatedBy = v.CreatedBy
		st.Postage = v.Postage
		totalMoney += st.TotalMoney
		totalProNumber += st.ProductNumber

		statistics = append(statistics, st)
	}

	total := &EntryStatistics{}
	total.Identifier = "总计"
	total.TotalMoney = totalMoney
	total.ProductNumber = totalProNumber
	statistics = append(statistics, total)

	return statistics, nil

}

//出入库明细
type EntryDetailedStatistics struct {
	Identifier   string //单据号
	DepName      string //门店
	TypeName     string
	Amount       int64 //产品数量
	ProductName  string
	Diopter      string
	Astigmatism  string
	ColourNumber string
	ModelNumber  string
	UnitPrice    float64
	SmallPlan    float64 //小计金额
	CreatedAt    string  //创建时间
	CreatedBy    string  //创建人
	Remarks      string
}

func (q *QueryParamsStatistics) EntryDetailed() ([]*EntryDetailedStatistics, error) {
	query := orm.NewOrm().QueryTable(models.ErpEntryDataTableName()).RelatedSel("Entry", "Products")

	cond := orm.NewCondition()
	cond = cond.AndCond(cond.And("entry__created_at__gte", utils.GetTimeParse(q.StartDate)).And("entry__created_at__lte", utils.GetTimeParse(q.EndDate)))

	if q.DepartmentId > 0 {
		cond = cond.And("entry__department_id", q.DepartmentId)
	}
	if q.TypeId > 0 {
		cond = cond.And("entry__typeid", q.TypeId)
	}
	if len(q.Filter) > 0 {
		cond = cond.And("entry__number", q.Filter)
	}
	cond = cond.And("entry__auditing", 4)
	query = query.SetCond(cond)
	erpEntryData := make([]*models.ErpEntryData, 0)

	if _, err := query.All(&erpEntryData); err != nil {
		return nil, err
	}
	statistics := make([]*EntryDetailedStatistics, 0)

	deps := q.StatisticsGetDepartment()

	for _, v := range erpEntryData {
		st := &EntryDetailedStatistics{}
		st.Identifier = v.Entry.Number //单号
		if n, ok := deps[v.Entry.DepartmentId]; ok {
			st.DepName = n["Name"].(string)
		}

		st.ProductName = v.Products.Name
		st.Amount = v.Amount
		st.UnitPrice = v.UnitPrice
		st.Diopter = v.Diopter
		st.Astigmatism = v.Astigmatism
		st.ModelNumber = v.ModelNumber
		st.ColourNumber = v.ColourNumber
		st.CreatedBy = v.Entry.CreatedBy
		st.CreatedAt = utils.GetDate(v.Entry.CreatedAt)
		st.SmallPlan = v.SmallPlan
		st.Remarks = v.Remarks

		statistics = append(statistics, st)
	}

	return statistics, nil
}

//运营报表统计
func (q *QueryParamsStatistics) Operate() (map[string]map[int]map[string]float64, error) {

	result := make(map[string]map[int]map[string]float64)
	//获取销售信息
	query := orm.NewOrm().QueryTable(models.RetailsDataTableName()).RelatedSel("Retails", "Products")
	cond := orm.NewCondition()
	cond = cond.AndCond(cond.And("retails__created_at__gte", utils.GetTimeParse(q.StartDate)).And("retails__created_at__lte", utils.GetTimeParse(q.EndDate)))
	if q.DepartmentId > 0 {
		cond = cond.And("retails__department_id", q.DepartmentId)
	}
	if len(q.Filter) > 0 {
		cond = cond.And("retails__manual_number", q.Filter)
	}
	query = query.SetCond(cond)
	retailsData := make([]*models.RetailsData, 0)
	if _, err := query.All(&retailsData); err != nil {
		return nil, err
	}

	eprtypeid := models.GetErpTypeid()
	eprtypeid[71] = "检查"
	for k, _ := range retailsData {  //组识配镜销售数据
	 	v := retailsData[k]
		if v.Retails.IsPayment != 5 {
			continue;
		}
		date := utils.GetDate(v.Retails.CreatedAt)
		tid := v.Products.TypeId
		zje := v.OriginalPrice
		yh, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", (v.OriginalPrice - (v.OriginalPrice * (v.DiscountRate / 100)))), 64)
		yf := v.TotalPrice

		if _, ok := result[date]; !ok {
			child := make(map[int]map[string]float64)
			for k, _ := range eprtypeid { //预设类型
				child[k] = map[string]float64{"zje": 0, "yh": 0, "yf": 0}
			}
			result[date] = child
		}
		result[date][tid]["zje"] = result[date][tid]["zje"] + zje
		result[date][tid]["yh"] = result[date][tid]["yh"] + yh
		result[date][tid]["yf"] = result[date][tid]["yf"] + yf
	}
	var params models.SaCollectfeesDoctororderMiddleQueryParam
	params.DepartmentId = q.DepartmentId
	params.StartDate = q.StartDate
	params.EndDate = q.EndDate
	data:=   models.SaCollectfeesDoctororderMiddleList(&params)
	if len(data) > 0 {
		for k,_ := range data {
			v := data[k]
			date := utils.GetDate(v.CreatedAt)
			if _, ok := result[date]; !ok {
				child := make(map[int]map[string]float64)
				for k, _ := range eprtypeid { //预设类型
					child[k] = map[string]float64{"zje": 0, "yh": 0, "yf": 0}
				}
				result[date] = child
			}
			zje := v.TotalMoney
			yh := float64(0)
			yf := v.SumPayable
			if v.Doctororder.ProjectType == "drug" {
				result[date][70]["zje"] = result[date][70]["zje"] + zje
				result[date][70]["yh"] = result[date][70]["yh"] + yh
				result[date][70]["yf"] = result[date][70]["yf"] + yf
			} else {
				result[date][71]["zje"] = result[date][71]["zje"] + zje
				result[date][71]["yh"] = result[date][71]["yh"] + yh
				result[date][71]["yf"] = result[date][71]["yf"] + yf
			}
		}
	}
	return result, nil
}

//调拨汇总
func (q *QueryParamsStatistics) Stock(suppliers_id int64, product_name string) (map[int64]map[string]interface{}, error) {
	query := &models.ErpInventoryQueryParam{}
	query.Department = q.DepartmentId
	query.Suppliers = suppliers_id
	query.Filter = product_name
	lists := models.ErpInventoryList(query)
	if len(lists) == 0 {
		return nil, errors.New("没有找到库存数据")
	}
	result := make(map[int64]map[string]interface{})
	values := make(map[int64][]interface{})
	for k,_ := range lists {
		value := lists[k]
		supplier_id := value.Products.Suppliers.Id
		supplier_name := value.Products.Suppliers.Name
		if _,ok := result[supplier_id]; !ok {
			result[supplier_id] = make(map[string]interface{})
			result[supplier_id]["name"] =  supplier_name
			result[supplier_id]["value"] = make([]interface{}, 0)
		}
		values[supplier_id] = append(values[supplier_id], value)
	}
	for k,_ := range result {
		result[k]["value"] = values[k]
	}
	return result, nil
}
